package com.cr.web.controller.common;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cr.common.config.CarIdentificationConfig;
import com.cr.common.config.ZnwdConfig;
import com.cr.framework.config.ServerConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import okhttp3.*;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.cr.common.config.RuoYiConfig;
import com.cr.common.constant.Constants;
import com.cr.common.core.domain.AjaxResult;
import com.cr.common.utils.StringUtils;
import com.cr.common.utils.file.FileUploadUtils;
import com.cr.common.utils.file.FileUtils;

/**
 * 通用请求处理
 */
@RestController
@RequestMapping("/common")
public class CommonController {
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);
    @Autowired
    private ServerConfig serverConfig;
    private static final String FILE_DELIMETER = ",";
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    public CarIdentificationConfig carIdentificationConfig;
    @Autowired
    public ZnwdConfig znwdConfig;

    public static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();


    /**
     * 通用下载请求
     * 
     * @param fileName 文件名称
     * @param delete 是否删除
     */
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(fileName))
            {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = RuoYiConfig.getDownloadPath() + fileName;

            response.setContentType(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete)
            {
                FileUtils.deleteFile(filePath);
            }
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 通用上传请求（单个）
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file)
    {
        try
        {
            // 获取当前日期时间
            String dateTime = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))+"/";
            // 文件上传
            FileInfo fileInfo = fileStorageService.of(file)
                    .setPath(dateTime) //保存到相对路径下，为了方便管理，不需要可以不写
                    .upload();  //将文件上传到对应地方
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", fileInfo.getUrl());
            ajax.put("fileName", fileInfo.getUrl());    // 使用URL保存文件的情况下，前端是默认返回的
            ajax.put("newFileName", fileInfo.getUrl());
            ajax.put("originalFilename", file.getOriginalFilename());
            // 识别车辆信息
            String result = getCarInfo(file);
            ajax = parseCarInfo(result,ajax);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 通用上传请求（多个）
     */
    @PostMapping("/uploads")
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files)
            {
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = RuoYiConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

    /**
     *   车辆识别，获取品牌、颜色等信息
     */
    public String getCarInfo(MultipartFile file) throws IOException {
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("image", "image.jpg", RequestBody.create(MediaType.parse("image/jpeg"), convertMultipartFileToBase64(file)))
                .build();
        Request request = new Request.Builder()
                .url(carIdentificationConfig.getUrl() + carIdentificationConfig.getAccessToken())
                .post(requestBody)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        return response.body().string();
    }


    /**
     *    MultipartFile转换为图像数据，且进行Base64编码
     */
    public String convertMultipartFileToBase64(MultipartFile multipartFile) throws IOException {
        // 读取MultipartFile为BufferedImage
        InputStream inputStream = multipartFile.getInputStream();
        BufferedImage image = ImageIO.read(inputStream);

        // 将BufferedImage转换为字节数组
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", baos); // 假设图像格式为JPEG
        byte[] imageBytes = baos.toByteArray();

        // 对字节数组进行Base64编码
        String base64Image = Base64.getEncoder().encodeToString(imageBytes);

        baos.close();
        inputStream.close();
        return base64Image;
    }

    /**
     *   解析车辆识别结果
     */
    public AjaxResult parseCarInfo(String carInfo,AjaxResult ajax) throws Exception {
        JSONObject jsonObject = new JSONObject(carInfo);
        JSONArray resultArray = jsonObject.getJSONArray("result");
        JSONObject carObject = resultArray.getJSONObject(0);
        // 获取品牌
        String brand = carObject.getString("name");
        // 获取颜色
        String colorResult = jsonObject.getString("color_result");
        // 根据品牌、颜色获取座位数、价格、年份、详情等信息
        ajax = getCarInfo(ajax,brand,colorResult);
        ajax.put("brand",brand);
        ajax.put("color",colorResult);
        return ajax;
    }

    /**
     *      补齐车辆属性
     */
    public AjaxResult getCarInfo(AjaxResult ajax,String carBrand,String carColor) throws Exception {
        //提示词工程
        String prompt ="假如我有一辆车为“大众TROC”，它的基本信息为：\n" +
                "{\n" +
                "  \"brand\":\"大众TROC\",\n" +
                "  \"seatingCapacity\":\"5座\",\n" +
                "  \"color\":\"白色\",\n" +
                "  \"year\":\"2018\",\n" +
                "  \"detail\":\"大众TROC，中文名称为“探歌”，是一汽-大众旗下的一款紧凑型SUV，自上市以来凭借其时尚的外观、宽敞的空间、丰富的配置以及出色的动力性能赢得了市场的广泛认可。\"\n" +
                "}\n" +
                "\n" +
                "我想租一辆车，请告诉我\""+carColor+carBrand+"\"的详情信息，请根据以上的方式回答，有多种答案的情况下，可以为最常见的一种，答案不要出现其他字眼\n";
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType,question(prompt));
        Request request = new Request.Builder()
                .url(znwdConfig.getUrl() + znwdConfig.getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        String result = response.body().string();
        // 处理结果
        JSONObject resultJsonObject = new JSONObject(new JSONObject(result).getString("result"));
        String year = resultJsonObject.getString("year");
        String seatingCapacity = resultJsonObject.getString("seatingCapacity");
        String detail = resultJsonObject.getString("detail");
        ajax.put("year",year);
        ajax.put("seatingCapacity",seatingCapacity);
        ajax.put("detail",detail);
        return ajax;
    }

    // 提问方式（一轮就够了）
    public String question(String message){
        ObjectMapper mapper = new ObjectMapper();
        // 创建一个 ObjectNode
        ObjectNode root = mapper.createObjectNode();
        // 创建一个 ArrayNode 用于存储消息
        ObjectNode userMessage = mapper.createObjectNode();
        userMessage.put("role","user");
        userMessage.put("content", message);
        // 将消息添加到 ArrayNode
        ArrayNode messagesArray = mapper.createArrayNode().add(userMessage);
        // 将 ArrayNode 添加到根节点
        root.set("messages", messagesArray);
        return root.toString();
    }
}
